package com.xxxx.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.server.enums.EnabledChangeEnum;
import com.xxxx.server.exception.ParamsException;
import com.xxxx.server.mapper.AdminMapper;
import com.xxxx.server.mapper.AdminRoleMapper;
import com.xxxx.server.mapper.RoleMapper;
import com.xxxx.server.mapper.SysMsgMapper;
import com.xxxx.server.pojo.Admin;
import com.xxxx.server.pojo.AdminRole;
import com.xxxx.server.pojo.RespBean;
import com.xxxx.server.pojo.Role;
import com.xxxx.server.service.IAdminService;
import com.xxxx.server.utils.AssertUtil;
import com.xxxx.server.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhoubin
 * @since 2020-09-07
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {

	@Autowired
	private UserDetailsService userDetailsService;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Resource
	private AdminMapper adminMapper;
	@Autowired
	private JwtUtil jwtUtil;
	@Value("${jwt.tokenHead}")
	private String tokenHead;
	@Resource
	private RoleMapper roleMapper;
	@Resource
	private AdminRoleMapper adminRoleMapper;
	@Resource
	private SysMsgMapper sysMsgMapper;

	private static final Integer DEFAULT_ROLE_ID = 9;



	/**
	 * 登录
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	@Override
	public RespBean login(String username, String password, String code, HttpServletRequest request) {
		UserDetails userDetails = userDetailsService.loadUserByUsername(username);
		if (null == userDetails || !passwordEncoder.matches(password, userDetails.getPassword())) {
			return RespBean.error("用户名或密码不正确！");
		}
		if (!userDetails.isEnabled()) {
			return RespBean.error("用户被禁用，请联系管理员！");
		}
		//判断验证码
		if(StringUtils.isEmpty(code) || !request.getSession().getAttribute("captcha").equals(code)){
			return RespBean.error("验证码错误！");
		}
		//将用户对象存入SpringSecurity全局上下文中，方便其他方法获取用户对象
		UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,
				null, userDetails.getAuthorities());
		SecurityContextHolder.getContext().setAuthentication(authenticationToken);
		String token = jwtUtil.generatorToken(userDetails);
		Map<String, Object> map = new HashMap<>();
		map.put("tokenHead", tokenHead);
		map.put("token", token);
		return RespBean.success("登录成功！", map);
	}

	/**
	 * 根据用户名获取用户对象
	 * @param username
	 * @return
	 */
	@Override
	public Admin getAdminByUserName(String username) {
		Admin admin = adminMapper.selectOne(new QueryWrapper<Admin>().eq("username", username));
		return admin;
	}

	/**
	 * 根据用户id获取角色
	 * @param adminId
	 * @return
	 */
	@Override
	public List<Role> getRoles(Integer adminId) {
		return roleMapper.getRoles(adminId);
	}



	/**
	 * 查询操作员管理
	 * @param keywords
	 * @return
	 */
	@Override
	public List<Admin> selectAdminList(String keywords) {


		// 设置查询条件
		QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();

		// 如果传递keywords，条件搜索
		if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(keywords) && !"".equals(keywords)) {
			queryWrapper.like("name", keywords);
		}
		// 查询操作员列表
		List<Admin> adminList = adminMapper.selectList(queryWrapper);
		// 查询角色
		adminList.forEach(admin -> {
			// 设置角色信息
			admin.setRoles(getRoles(admin.getId()));
			// 将密码设为null
			admin.setPassword(null);
		});
		return adminList;
	}

	/**
	 * 操作员管理更改权限
	 * @param admin
	 * @return
	 */
	@Override
	public EnabledChangeEnum enabledChange(Map<String, Object> admin) {


		Integer adminId = (Integer) admin.get("id");
		boolean enabled = (boolean) admin.get("enabled");

		// 创建参数对象
		Map<String, Object> map = new HashMap<>();
		map.put("id", adminId);
		map.put("enabled", enabled ? 1 : 0);

		if (enabled) {
			// 修改用户的enabled
			adminMapper.updateAdminEnabledById(map);
			return EnabledChangeEnum.ENABLE;

		} else if (!enabled) {

			// 修改用户的enabled
			adminMapper.updateAdminEnabledById(map);
			return EnabledChangeEnum.DISABLE;

		} else {
			return null;
		}
	}

	/**
	 * 操作员管理删除用户
	 * @param id
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteAdminById(Integer id) {
		// 判断是否存在要删除的用户
		AssertUtil.isTrue(null == id, "请选择要删除的用户！");

		// 删除用户绑定的角色信息
		deleteAdminRoleByAdminId(id);
		//删除用户绑定的msg信息
		AssertUtil.isTrue(sysMsgMapper.deleteByAdminId(id) < 0, "用户msg绑定删除失败！");
		// 删除用户
		AssertUtil.isTrue(adminMapper.deleteById(id) < 0, "用户删除失败！");

	}

	/**
	 *查询所有角色列表
	 * @return
	 */
	@Override
	public List<Role> selectAllRoleList() {
		return roleMapper.selectList(new QueryWrapper<Role>());
	}

	/**
	 * 修改用户角色信息
	 * @param adminId
	 * @param rids
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void updateAdminRole(Integer adminId, String rids) {

		//判断用户是否被禁用
		Admin admin = adminMapper.selectOne(new QueryWrapper<Admin>().eq("id",adminId));
		AssertUtil.isTrue(!admin.getEnabled(), "该用户已被禁用，请启用后在设置角色！");

		// 创建sql条件对象
		QueryWrapper<AdminRole> queryWrapper = new QueryWrapper<>();

		// 参数校验
		AssertUtil.isTrue(null == adminId || 0 == adminId, "用户不合法！");

		// 根据用户id删除原有的角色数据
		deleteAdminRoleByAdminId(adminId);
		// 清空queryWrapper中的条件
		queryWrapper.clear();

		//  判断是否有角色数据绑定
		if (StringUtils.isNotBlank(rids)) {

			// 将rids转为数组
			String[] ridStrs = rids.split(",");

			// 添加标识
			int insCount = 0;
			// 为该用户绑定新的角色数据
			AdminRole adminRole = new AdminRole();
			adminRole.setAdminId(adminId);
			for (String rid : ridStrs) {
				adminRole.setRid(Integer.parseInt(rid));
				adminRoleMapper.insert(adminRole);
				insCount++;
			}
			AssertUtil.isTrue(insCount < ridStrs.length, "用户角色绑定失败！");
		} else {
			// 没有权限绑定默认权限
			AdminRole adminRole = new AdminRole();
			adminRole.setAdminId(adminId);
			adminRole.setRid(DEFAULT_ROLE_ID);
		}
	}

    @Override
    public boolean updateAdminInfo(Map<String,Object> map) {
		//根据map手动封装admin数据，因为只需要修改这些数据所以只封装这些
		final Admin admin = new Admin();
		admin.setId((Integer) map.get("id"));
		admin.setName((String) map.get("name"));
		admin.setPhone((String) map.get("phone"));
		admin.setTelephone((String) map.get("telephone"));
		admin.setAddress((String) map.get("address"));
		//非空判断
		if(
				StringUtils.checkValNull(admin.getId()) ||
				StringUtils.checkValNull(admin.getName()) ||
				StringUtils.checkValNull(admin.getPhone()) ||
				StringUtils.checkValNull(admin.getTelephone()) ||
				StringUtils.checkValNull(admin.getAddress())
		){
			throw new ParamsException("修改的值不能为空");
		}
		//如果手机号码的位数超过11抛出异常
		if(admin.getPhone().length()>11){
			throw new ParamsException("请正确输入11位手机号码!");
		}
		return adminMapper.updateAdminInfoById(admin);
    }

    @Override
    public boolean updateAdminPasswordInfo(LinkedHashMap<String, Object> map) {
		//获取当前用户对象
		final Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		//获取当前用户对象的加密密码
		String oldPass = admin.getPassword();
		//获取前端输入的修改密码
		String pass = (String) map.get("pass");
		//获取前端输入的旧密码
		String oldPassParam = (String) map.get("oldPass");
		//非空判断
		if(
				StringUtils.checkValNull(map.get("adminId")) ||
						StringUtils.checkValNull(pass) ||
						StringUtils.checkValNull(map.get("checkPass")) ||
						StringUtils.checkValNull(oldPassParam)
		){
			throw new ParamsException("修改的值不能为空");
		}
		//如果旧密码和原始密码不一致抛出异常
		if(!passwordEncoder.matches(oldPassParam,oldPass)){
			throw new ParamsException("输入的旧密码与原始密码不一致！");
		}
		//将新密码加密
		pass = passwordEncoder.encode(pass);
		//移除旧密码，添加新密码
		map.remove("pass");
		map.put("pass",pass);
		return adminMapper.updateAdminPasswordInfo(map);
    }

    @Override
    public boolean updateAdminUserFaceById(Integer id,String path) {

		return adminMapper.updateAdminUserFaceById(id,path);
    }

    /**
	 * 根据用户id删除相关的角色信息
	 * @param adminId
	 */
	private void deleteAdminRoleByAdminId(Integer adminId) {

		// 创建sql条件对象
		QueryWrapper<AdminRole> queryWrapper = new QueryWrapper<>();
		// 根据用户id查询该用户具有的角色数量
		Integer count = adminRoleMapper.selectCount(queryWrapper.eq("adminId", adminId));
		if (count > 0) {
			// 删除原有角色数据
			int delRows = adminRoleMapper.delete(queryWrapper);
			AssertUtil.isTrue(delRows < count, "用户信息重置失败！");
		}

	}
}
